package com.gitee.target123.develop.common.httpclient;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * 网络请求工具
 */
public abstract class AbstractHttpClientUtil {

	private final static Logger LOGGER = LoggerFactory.getLogger(AbstractHttpClientUtil.class);

	protected final CloseableHttpClient closeableHttpClient;

	public AbstractHttpClientUtil() {
		closeableHttpClient = initHttpClient();
	}

	protected abstract CloseableHttpClient initHttpClient();

	public String doGet(String url){
		return doGet(url,null);
	}
	public String doGet(String url, Map<String,Object> params){
		return doGetWithHeader(url,params,null);
	}
	public String doGetWithHeader(String url, Map<String,String> headers){
		return doGetWithHeader(url,null,headers);
	}
	public String doGetWithHeader(String url, Map<String,Object> params, Map<String,String> headers){
		String getUrl = url;
		if (params!=null && !params.isEmpty()){
			StringBuilder builder = new StringBuilder();
			params.forEach((k, v) -> {
				if (v!=null){
					if (builder.length() > 0) {
						builder.append("&");
					}
					builder.append(k).append("=").append(v);
				}
			});
			getUrl += ("?" + builder.toString());
		}
		HttpGet httpGet = new HttpGet(getUrl);
		if (headers!=null && !headers.isEmpty()){
			headers.forEach(httpGet::addHeader);
		}
		return execute(httpGet,this::entityToString);
	}

	public String doPost(String url, List<NameValuePair> params){
		return doPostWithHeader(url,params,null);
	}
	public String doPost(String url, String json){
		return doPostWithHeader(url,json,null);
	}
	public String doPostWithHeader(String url, List<NameValuePair> params, Map<String,String> headers){
		HttpEntity entity = EntityBuilder.create()
				.setParameters(params)
				.build();
		return doPostWithHeader(url,entity,headers);
	}
	public String doPostWithHeader(String url, String json, Map<String,String> headers){
		HttpEntity entity = EntityBuilder.create()
				.setText(json)
				.setContentType(ContentType.APPLICATION_JSON)
				.build();
		return doPostWithHeader(url,entity,headers);
	}
	public String doPostWithHeader(String url, HttpEntity entity, Map<String,String> headers){
		HttpPost httpPost = new HttpPost(url);
		httpPost.setEntity(entity);
		if (headers!=null && !headers.isEmpty()){
			headers.forEach(httpPost::addHeader);
		}
		return execute(httpPost,this::entityToString);
	}

	protected final <R> R execute(HttpUriRequest request, Function<HttpEntity,R> resultConvert){
		CloseableHttpResponse response = null;
		try {
			response = closeableHttpClient.execute(request);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				return resultConvert.apply(response.getEntity());
			}
		}catch (Exception e){
			LOGGER.error("httpClient execute fail!",e);
		}finally {
			HttpClientUtils.closeQuietly(response);
		}
		return null;
	}

	protected String entityToString(HttpEntity entity) {
		try {
			return EntityUtils.toString(entity,StandardCharsets.UTF_8);
		} catch (IOException e) {
			LOGGER.error("httpClient response entity resultToString fail!",e);
			return null;
		}
	}

	protected byte[] entityToByteArray(HttpEntity entity) {
		try {
			return EntityUtils.toByteArray(entity);
		} catch (IOException e) {
			LOGGER.error("httpClient response entity resultToByteArray fail!",e);
			return null;
		}
	}

}
